import React from "react";
import { Modal, message } from "antd";
import { Controlled as CodeMirror } from "react-codemirror2";
import typeOf from "typeof";
import { InnerField } from "src/utils/interface";

import "codemirror/addon/fold/foldcode.js"; // 代码折叠
import "codemirror/addon/fold/foldgutter.js"; // 代码折叠
import "codemirror/addon/fold/brace-fold.js"; // 代码折叠
import "codemirror/addon/fold/comment-fold.js"; // 代码折叠
import "codemirror/addon/selection/active-line.js"; // 当前行高亮
import "codemirror/lib/codemirror.js";
import "codemirror/mode/javascript/javascript.js";
// css
import "codemirror/addon/fold/foldgutter.css"; // 代码折叠
import "codemirror/addon/hint/show-hint.css"; // 自动提示
import "codemirror/lib/codemirror.css"; // 编辑器样式
import "codemirror/theme/idea.css"; // 主题: idea

const { useState } = React;

interface Props {
  visible: boolean;
  setVisible: (visible: boolean) => void;
  onChange: (value: any) => void;
}

const ImportJSONModal: React.FC<Props> = (props) => {
  const [value, setValue] = useState("");

  const typeOfFn = (v: any): string => {
    switch (typeOf(v)) {
      case "number":
        if (parseInt(v) !== v) return "float";
        if (v === 0 || v === 1) return "boolean";
        return "int16";

      case "string":
        return "string";

      case "date":
        return "time.Time";

      case "object":
        return "struct";

      case "array":
        if (v.length === 0) {
          return "string[]";
        }
        return `${typeOfFn((v as any[])[0])}[]`;

      default:
        return "";
    }
  };

  const structArrayInnerFieldsType = (
    v: any[],
    isTwoDimensionalArray: boolean
  ): InnerField[] => {
    const allProps = isTwoDimensionalArray
      ? (v
          .flat()
          .map((item) => importJSON(item))
          .flat() as InnerField[])
      : (v.map((item) => importJSON(item)).flat() as InnerField[]);
    const map: Record<string, InnerField[]> = {};
    allProps
      .filter((item) => item !== undefined)
      .forEach((item) => {
        if (map[item.name]) {
          map[(item as InnerField).name].push(item);
        } else {
          map[item.name] = [item];
        }
      });

    const innerFields = [] as InnerField[];
    for (let k in map) {
      const types = map[k].map((item) => item.type);
      let type;
      if (types.indexOf("float") !== -1) type = "float";
      else if (types.indexOf("int16") !== -1) type = "int16";
      else if (types.indexOf("boolean") !== -1) type = "boolean";
      innerFields.push({ ...map[k][0], type: type || types[0] });
    }
    return innerFields;
  };

  const handleJSONArray = (
    name: string,
    type: string,
    v: any[]
  ): InnerField => {
    const isTwoDimensionalArray = type.indexOf("[][]") !== -1;
    const isStructArray = type.indexOf("struct[]") !== -1;
    const field = { name, type: "list" } as InnerField;
    let otherProps;

    if (!isTwoDimensionalArray && !isStructArray) {
      otherProps = {
        itemType: type.split("[]")[0],
      };
    } else if (isTwoDimensionalArray && !isStructArray) {
      otherProps = {
        itemType: "list",
        itemType2: type.split("[][]")[0],
      };
    } else if (!isTwoDimensionalArray && isStructArray) {
      otherProps = {
        itemType: "struct",
        innerFields: structArrayInnerFieldsType(v, false),
      };
    } else if (isTwoDimensionalArray && isStructArray) {
      otherProps = {
        itemType: "list",
        itemType2: "struct",
        innerFields: structArrayInnerFieldsType(v, true),
      };
    }
    return { ...field, ...otherProps };
  };

  const importJSON = (json: Record<string, any> | any[]) => {
    const innerFields: InnerField[] = [];
    const isArray = (type: string) => type.indexOf("[]") !== -1;

    if (typeOfFn(json) === "struct") {
      for (let k in json) {
        const name = k;
        const v = (json as Record<string, any>)[k];
        const type = typeOfFn(v);
        if (type !== "struct" && type.indexOf("[]") === -1) {
          innerFields.push({ name, type });
        } else if (type === "struct") {
          innerFields.push({ name, type, innerFields: importJSON(v) });
        } else if (isArray(type)) {
          innerFields.push(handleJSONArray(name, type, v));
        }
      }
      return innerFields;
    }

    if (isArray(typeOfFn(json))) {
      const field = handleJSONArray("", typeOfFn(json), json as any[]);
      return field.innerFields;
    }
  };

  return (
    <Modal
      title="Import JSON"
      visible={props.visible}
      onOk={() => {
        try {
          const obj = JSON.parse(value);
          const innerFields = importJSON(obj);
          props.onChange(innerFields);
          props.setVisible(false);
        } catch (e) {
          message.error("请输入合法的 JSON 字符串");
          console.error(e);
        }
      }}
      onCancel={() => props.setVisible(false)}
    >
      <CodeMirror
        value={value}
        options={{
          mode: "javascript",
          theme: "idea", // 主题配置
          lineNumbers: true, // 显示行号
          lineWrapping: true, // 自动换行
          styleActiveLine: true, // 选中行高亮
          matchBrackets: true, // 匹配括号
          indentUnit: 4, // 缩进配置（默认为2）
        }}
        onBeforeChange={(editor, data, v) => setValue(v)}
      />
    </Modal>
  );
};

export default ImportJSONModal;
